home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / libraries / easylibs.lha / EasyLibs / fd2pragma.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-05  |  28.2 KB  |  1,255 lines

  1. /*
  2.     fd2pragma.c
  3.  
  4.     This is a small little hack which converts fd-files to either
  5.     pragmas readable by a C-Compiler of LVO files readable by an
  6.     assembler. Use it as you want, but WITHOUT ANY WARRANTY!
  7.  
  8.     V1.2:   Added pragmas for the Dice compiler. Available via switch "Dice".
  9.         Added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
  10.         turn on the default (except that Maxon expects pragma files to be
  11.         called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
  12.         Dice, except that SAS supports the pragma tagcall.
  13.  
  14.     V2.0:   Added support for tag functions. See the docs for details.
  15.     V2.1:   Minor bugfix; added support of PRAGMAS_DECLARING_LIBBASE
  16.     V2.2:   Added the possibility to create a libraries function table.
  17.             (See LibHeader.c)
  18.  
  19.     Computer: Amiga 1200            Compiler: Aztec-C V5.0a
  20.                               Dice 3.01
  21.  
  22.     Author:    Jochen Wiedmann
  23.         Am Eisteich 9
  24.       72555 Metzingen (Germany)
  25.         Tel. 07123 / 14881
  26.         Internet: wiedmann@zdv.uni-tuebingen.de
  27. */
  28.  
  29.  
  30.  
  31.  
  32.  
  33. /*
  34.     Include files
  35. */
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <exec/nodes.h>
  41. #include <exec/lists.h>
  42. #include <exec/libraries.h>
  43. #include <exec/memory.h>
  44. #include <exec/interrupts.h>
  45. #include <exec/ports.h>
  46. #include <exec/devices.h>
  47. #include <exec/io.h>
  48. #include <clib/exec_protos.h>
  49. #include <clib/alib_protos.h>
  50. #include <clib/dos_protos.h>
  51.  
  52. #ifdef AZTEC_C
  53. #include <pragmas/exec_lib.h>
  54. #include <pragmas/dos_lib.h>
  55. #endif
  56.  
  57. #if defined(_DCC)  ||  defined(__SASC)  ||  defined(__MAXON)
  58. #include <pragmas/exec_pragmas.h>
  59. #include <pragmas/dos_pragmas.h>
  60. #endif
  61.  
  62. #ifdef __GNUC__
  63. #include <inline/exec.h>
  64. #include <inline/dos.h>
  65. #endif
  66.  
  67. extern struct Library *SysBase;
  68. extern struct Library *DOSBase;
  69.  
  70.  
  71.  
  72.  
  73.  
  74. /*
  75.     Constants
  76. */
  77. #define MAXNAMELEN 128
  78.  
  79. const UBYTE VERSION[] = "$VER: fd2pragma 2.2 (04.07.94)   by  Jochen Wiedmann";
  80. const UBYTE TEMPLATE[] =
  81.     "FDFILE/A,AZTEC/K,AS/K,SAS/K,DICE/K,MAXON/K,TAGDIR/K,FUNCTABLE/K,HELP/S";
  82.  
  83. const STRPTR RegNames[16] =
  84. { (STRPTR) "d0", (STRPTR) "d1", (STRPTR) "d2", (STRPTR) "d3",
  85.   (STRPTR) "d4", (STRPTR) "d5", (STRPTR) "d6", (STRPTR) "d7",
  86.   (STRPTR) "a0", (STRPTR) "a1", (STRPTR) "a2", (STRPTR) "a3",
  87.   (STRPTR) "a4", (STRPTR) "a5", (STRPTR) "a6", (STRPTR) "a7"
  88. };
  89.  
  90. const UBYTE HexDigits[17] = "0123456789ABCDEF";
  91.  
  92.  
  93.  
  94. /*
  95.     This structure is used to represent the pragmas that are read.
  96. */
  97. struct AmiPragma
  98. { struct MinNode Node;
  99.   LONG Bias;
  100.   LONG Public;
  101.   STRPTR FuncName;
  102.   STRPTR TagName;
  103.   ULONG NumArgs;
  104.   struct
  105.   { STRPTR ArgName;
  106.     ULONG ArgReg;
  107.   } Args[14];    /*  a6 and a7 must not be used for function arguments    */
  108. };
  109.  
  110.  
  111.  
  112.  
  113.  
  114. /*
  115.     Global variables
  116. */
  117. struct MinList AmiPragmaList;
  118. STRPTR BaseName;
  119. STRPTR ShortBaseName;
  120.  
  121.  
  122.  
  123.  
  124.  
  125. /*
  126.     This function works similar to strdup, but doesn't duplicate the
  127.     whole string.
  128.  
  129.     Inputs: Str - the string to be duplicated
  130.         Len - the number of bytes to be duplicated
  131.  
  132.     Result: Pointer to the copy of the string or NULL.
  133. */
  134. STRPTR strndup(const STRPTR Str, ULONG Len)
  135.  
  136. { STRPTR result;
  137.  
  138.   if ((result = malloc(Len+1)))
  139.   { memcpy(result, Str, Len);
  140.     result[Len] = '\0';
  141.   }
  142.   return(result);
  143. }
  144.  
  145.  
  146.  
  147.  
  148.  
  149. /*
  150.     This function prints help information.
  151. */
  152. void Usage(void)
  153.  
  154. { fprintf(stderr, "\nUsage: fd2pragma %s\n\n", TEMPLATE);
  155.  
  156.   fprintf(stderr, "This program reads the given FDFILE and converts it ");
  157.   fprintf(stderr, "into pragmas for\n");
  158.   fprintf(stderr, "a C-Compiler (SAS, Dice, Aztec or Maxon) or LVO files ");
  159.   fprintf(stderr, "for an\n");
  160.   fprintf(stderr, "Assembler (Aztec-As).\n\n");
  161.   fprintf(stderr, "FUNCTABLE is the name of a file where to store a ");
  162.   fprintf(stderr, "function table\n");
  163.   fprintf(stderr, "called LibFuncTable which describes the LVO table. (See ");
  164.   fprintf(stderr, "LibHeader.c)\n\n");
  165.   fprintf(stderr, "TAGDIR is the name of a directory where to store stub ");
  166.   fprintf(stderr, "routines for\n");
  167.   fprintf(stderr, "pragma functions, if any are found. \"\" is the current ");
  168.   fprintf(stderr, "directory.\n\n\n");
  169.   fprintf(stderr, "%s\n\n", VERSION+6);
  170.   fprintf(stderr,
  171.       "This is public domain, use it as you want, but WITHOUT ANY WARRANTY!\n");
  172.   fprintf(stderr,
  173.       "Bugs and suggestions to wiedmann@mailserv.zdv.uni-tuebingen.de.\n\n");
  174.  
  175.   exit (1);
  176. }
  177.  
  178.  
  179.  
  180.  
  181.  
  182. /*
  183.     This function is used to skip over blanks.
  184.  
  185.     Inputs: OldPtr  - pointer to the beginning of a string.
  186.  
  187.     Result: Pointer to the first nonblank character of the string.
  188. */
  189. STRPTR SkipBlanks(const STRPTR OldPtr)
  190.  
  191. { STRPTR oldptr = OldPtr;
  192.  
  193.   while (*oldptr == ' '  ||  *oldptr == '\t')
  194.   { ++oldptr;
  195.   }
  196.   return(oldptr);
  197. }
  198.  
  199.  
  200.  
  201.  
  202.  
  203. /*
  204.     This function is used to skip over variable names.
  205.  
  206.     Inputs: OldPtr  - pointer to the beginning of a string.
  207.  
  208.     Result: Pointer to the first character of the string, that is not one
  209.         of a-z, A-Z, 0-9 or the underscore.
  210. */
  211. STRPTR SkipName(const STRPTR OldPtr)
  212.  
  213. { STRPTR oldptr;
  214.   UBYTE c;
  215.  
  216.   oldptr = OldPtr;
  217.   while((c = *oldptr) == '_'  ||
  218.     (c >= '0'  &&  c <= '9')  ||
  219.     (c >= 'a'  &&  c <= 'z')  ||
  220.     (c >= 'A'  &&  c <= 'Z'))
  221.   { ++oldptr;
  222.   }
  223.   return(oldptr);
  224. }
  225.  
  226.  
  227.  
  228.  
  229.  
  230. /*
  231.     This function tells, that we ran out of memory.
  232. */
  233. void MemError(void)
  234.  
  235. { fprintf(stderr, "Fatal: Out of memory!\n");
  236. }
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243. /*
  244.     This function is called to scan the FD file.
  245.  
  246.     Inputs: FDFile  - the name of the file to scan
  247.  
  248.     Result: TRUE, if successful, FALSE otherwise
  249. */
  250. ULONG ScanFDFile(const STRPTR FDFile)
  251.  
  252. { FILE *fp;
  253.   ULONG public = TRUE;
  254.   ULONG bias = -1;
  255.   ULONG linenum = 0;
  256.   ULONG result = FALSE;
  257.   UBYTE line[512];
  258.  
  259.   if (!(fp = fopen((char *) FDFile, "r")))
  260.   { fprintf(stderr, "Fatal: Cannot open FD file %s.\n", FDFile);
  261.     return(FALSE);
  262.   }
  263.  
  264.   NewList((struct List *) &AmiPragmaList);
  265.  
  266.   while(fgets((char *) line, sizeof(line), fp)  !=  NULL)
  267.   { ULONG len;
  268.  
  269.     ++linenum;
  270.  
  271.     for (len = 0;  len < sizeof(line);  ++len)
  272.     { if (line[len] == '\n')
  273.       { break;
  274.       }
  275.     }
  276.     if (len == sizeof(line))
  277.     { int c;
  278.  
  279.       fprintf(stderr, "Error: Line %ld too long.\n", linenum);
  280.       while((c = getc(fp)) != EOF  &&  c != '\n')
  281.       {
  282.       }
  283.       continue;
  284.     }
  285.     line[len] = '\0';   /*  Remove Line Feed    */
  286.  
  287.     if (line[0] == '*')
  288.     { /*  Comment   */
  289.       STRPTR ptr;
  290.  
  291.       ptr = SkipBlanks(line+1);
  292.       if(strnicmp((char *) ptr, "tagcall", 7) == 0)  /*  Tag to create?  */
  293.       { struct AmiPragma *prevpragma;
  294.  
  295.     ptr = SkipBlanks(ptr+7);
  296.  
  297.     prevpragma = (struct AmiPragma *) AmiPragmaList.mlh_TailPred;
  298.     if (!prevpragma->Node.mln_Pred)
  299.     { fprintf(stderr,
  300.           "Line %ld, Error: Tag definition without preceding Pragma.\n",
  301.           linenum);
  302.       continue;
  303.     }
  304.  
  305.     if (prevpragma->TagName)
  306.     { fprintf(stderr, "Line %ld, Warning: Tag function redeclared.\n",
  307.           linenum);
  308.       continue;
  309.     }
  310.  
  311.     if (!prevpragma->NumArgs)
  312.     { fprintf(stderr,
  313.           "Line %ld, Error: Tag function must have arguments.\n",
  314.           linenum);
  315.     }
  316.  
  317.     /*
  318.         Get the tag functions name.
  319.     */
  320.     len = strlen((char *) prevpragma->FuncName)+strlen((char *) ptr)+1;
  321.  
  322.     if (!(prevpragma->TagName = strndup(prevpragma->FuncName, len)))
  323.     { MemError();
  324.       goto exit_ScanFDFile;
  325.     }
  326.  
  327.     if (!*ptr)
  328.     { len = strlen((char *) prevpragma->TagName);
  329.       if (prevpragma->TagName[len-1] == 'A')
  330.       { prevpragma->TagName[len-1] = '\0';
  331.       }
  332.     }
  333.     else
  334.     { STRPTR nextptr;
  335.  
  336.       if (*ptr == '=')
  337.       { ptr = SkipBlanks(ptr+1);
  338.         nextptr = SkipName(ptr);
  339.         if (!(len = nextptr-ptr))
  340.         { fprintf(stderr, "Line %ld, Error: Missing pragma name.\n",
  341.               linenum);
  342.           continue;
  343.         }
  344.         strncpy((char *) prevpragma->TagName, (char *) ptr, len);
  345.         prevpragma->TagName[len] = '\0';
  346.       }
  347.       else
  348.       { nextptr = SkipName(ptr);
  349.         if ((len = nextptr-ptr))
  350.         { STRPTR addptr;
  351.  
  352.           addptr = prevpragma->TagName + strlen(prevpragma->TagName);
  353.           *ptr = toupper(*ptr);
  354.           strncat((char *) addptr, (char *) ptr, len);
  355.           addptr[len] = '\0';
  356.         }
  357.         else
  358.         { fprintf(stderr, "Line %ld, Error: Missing pragma name.\n",
  359.               linenum);
  360.           continue;
  361.         }
  362.       }
  363.  
  364.       if (*SkipBlanks(nextptr))
  365.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  366.       }
  367.     }
  368.       }
  369.     }
  370.     else if (strnicmp((char *) line, "##base", 6) == 0)
  371.     { STRPTR ptr, nextptr;
  372.       LONG len;
  373.  
  374.       if (BaseName)
  375.       { fprintf(stderr, "Line %ld, Error: Basename declared twice.\n",
  376.         linenum);
  377.       }
  378.  
  379.       ptr = SkipBlanks(line+6);
  380.       if (*ptr != '_')
  381.       { fprintf(stderr, "Line %ld, Warning: Expected preceding _ in Basename.\n",
  382.         linenum);
  383.       }
  384.       else
  385.       { ++ptr;
  386.       }
  387.       nextptr = SkipName(ptr);
  388.       if ((len = nextptr-ptr))
  389.       { if (!(BaseName = strndup(ptr, len)))
  390.     { MemError();
  391.       goto exit_ScanFDFile;
  392.     }
  393.  
  394.     ptr = FilePart(FDFile);
  395.     len = strlen((char *) ptr)-7;
  396.     if (len >= 0  &&  stricmp((char *) ptr+len, "_lib.fd") == 0)
  397.     { if (!(ShortBaseName = (STRPTR) strdup((char *) ptr)))
  398.       { MemError();
  399.         goto exit_ScanFDFile;
  400.       }
  401.       ShortBaseName[len] = '\0';
  402.     }
  403.     else
  404.     { if (!(ShortBaseName = (STRPTR) strdup((char *) BaseName)))
  405.       { MemError();
  406.         goto exit_ScanFDFile;
  407.       }
  408.       len = strlen((char *) ShortBaseName)-4;
  409.       if (len >= 0  &&  stricmp((char *) ShortBaseName+len, "base") == 0)
  410.       { ShortBaseName[len] = '\0';
  411.       }
  412.     }
  413.  
  414.     if (*SkipBlanks(nextptr))
  415.     { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  416.     }
  417.       }
  418.       else
  419.       { fprintf(stderr, "Line %ld, Error: Expected Basename.\n", linenum);
  420.       }
  421.     }
  422.     else if (strnicmp((char *) line, "##bias", 6) == 0)
  423.     { STRPTR ptr;
  424.       LONG newbias;
  425.  
  426.       newbias = strtol((char *) line+6, (char **) &ptr, 0);
  427.       if (ptr == line+6)
  428.       { fprintf(stderr, "Line %ld, Error: Expected Bias value.\n", linenum);
  429.       }
  430.       else
  431.       { if (newbias < 0)
  432.     { fprintf(stderr, "Line %ld, warning: Assuming positive value.\n",
  433.           linenum);
  434.       bias = -newbias;
  435.     }
  436.     else
  437.     { bias = newbias;
  438.     }
  439.       }
  440.       if (*SkipBlanks(ptr))
  441.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  442.       }
  443.     }
  444.     else if (strnicmp((char *) line, "##end", 5) == 0)
  445.     { if (*SkipBlanks(line+5))
  446.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  447.       }
  448.       break;
  449.     }
  450.     else if (strnicmp((char *) line, "##public", 8) == 0)
  451.     { if (*SkipBlanks(line+8))
  452.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  453.       }
  454.       public = TRUE;
  455.     }
  456.     else if (strnicmp((char *) line, "##private", 9) == 0)
  457.     { if (*SkipBlanks(line+9))
  458.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  459.       }
  460.       public = FALSE;
  461.     }
  462.     else
  463.     { STRPTR ptr, nextptr;
  464.       struct AmiPragma *newpragma;
  465.       ULONG len, numargs;
  466.  
  467.       ptr = SkipBlanks(line);
  468.       nextptr = SkipName(ptr);
  469.       if (!(len = nextptr-ptr))
  470.       { fprintf(stderr, "Line %ld, Error: Missing function name\n", linenum);
  471.     continue;
  472.       }
  473.  
  474.       if (!(newpragma = calloc(sizeof(*newpragma), 1))  ||
  475.       !(newpragma->FuncName = strndup(ptr, len)))
  476.       { MemError();
  477.     goto exit_ScanFDFile;
  478.       }
  479.  
  480.       if (*(ptr = SkipBlanks(nextptr)) != '(')
  481.       { fprintf(stderr, "Line %ld, Error: Expected '('.\n", linenum);
  482.     continue;
  483.       }
  484.  
  485.       do
  486.       { ptr = SkipBlanks(ptr+1);
  487.  
  488.     if (*ptr == ')' && newpragma->NumArgs == 0)
  489.     { break;
  490.     }
  491.  
  492.     if (newpragma->NumArgs == 14)
  493.     { fprintf(stderr, "Line %ld, Error: Too much arguments.\n", linenum);
  494.     }
  495.  
  496.     nextptr = SkipName(ptr);
  497.     if (!(len = nextptr-ptr))
  498.     { fprintf(stderr, "Line %ld, Error: Expected argument name.\n",
  499.           linenum);
  500.       goto continue_loop;
  501.     }
  502.  
  503.     if (!(ptr = strndup(ptr, len)))
  504.     { MemError();
  505.       goto exit_ScanFDFile;
  506.     }
  507.     newpragma->Args[newpragma->NumArgs++].ArgName = ptr;
  508.  
  509.     ptr = SkipBlanks(nextptr);
  510.     if (*ptr != ','  &&  *ptr != '/'  &&  *ptr != ')')
  511.     { fprintf(stderr, "Line %ld, Error: Expected ')'.\n", linenum);
  512.       goto continue_loop;
  513.     }
  514.       }
  515.       while (*ptr != ')');
  516.  
  517.       if (*(ptr = SkipBlanks(ptr+1)) != '(')
  518.       { fprintf(stderr, "Line %ld, Error: Expected '('.\n", linenum);
  519.     continue;
  520.       }
  521.  
  522.       numargs = 0;
  523.       do
  524.       { ULONG i;
  525.  
  526.     ptr = SkipBlanks(ptr+1);
  527.  
  528.     if (*ptr == ')'  &&  numargs == 0)
  529.     { break;
  530.     }
  531.  
  532.     if (numargs > newpragma->NumArgs)
  533.     { fprintf(stderr,
  534.           "Line %ld, Error: Number of arguments != number of registers.\n",
  535.           linenum);
  536.       goto continue_loop;
  537.     }
  538.  
  539.     nextptr = SkipName(ptr);
  540.     if (!(len = nextptr-ptr))
  541.     { fprintf(stderr, "Line %ld, Error: Expected register name.\n",
  542.           linenum);
  543.       goto continue_loop;
  544.     }
  545.  
  546.     for (i = 0;  i < 16;  i++)
  547.     { if (strnicmp((char *) RegNames[i], (char *) ptr, len) == 0)
  548.       { break;
  549.       }
  550.     }
  551.  
  552.     if (i > 16)
  553.     { fprintf(stderr, "Line %ld, Error: Expected register name.\n",
  554.           linenum);
  555.       goto continue_loop;
  556.     }
  557.     if (i > 14)
  558.     { fprintf(stderr,
  559.           "Line %ld, Error: %s not allowed as argument register.\n",
  560.           linenum, RegNames[i]);
  561.       goto continue_loop;
  562.     }
  563.  
  564.     newpragma->Args[numargs].ArgReg = i;
  565.  
  566.     for (i = 0;  i < numargs;  i++)
  567.     { if (newpragma->Args[numargs].ArgReg == newpragma->Args[i].ArgReg)
  568.       { fprintf(stderr, "Line %ld, Error: Register %s used twice.\n",
  569.             linenum, RegNames[newpragma->Args[numargs].ArgReg]);
  570.         goto continue_loop;
  571.       }
  572.     }
  573.     ++numargs;
  574.  
  575.     ptr = SkipBlanks(nextptr);
  576.     if (*ptr != ','  &&  *ptr != '/'  &&  *ptr != ')')
  577.     { fprintf(stderr, "Line %ld, Error: Expected ')'.\n", linenum);
  578.       goto continue_loop;
  579.     }
  580.       }
  581.       while (*ptr != ')');
  582.  
  583.       if (numargs < newpragma->NumArgs)
  584.       { fprintf(stderr,
  585.         "Line %ld, Error: Number of arguments != number of registers.\n",
  586.         linenum);
  587.     goto continue_loop;
  588.       }
  589.  
  590.       if (bias == -1)
  591.       { fprintf(stderr, "Line %ld, warning: Assuming bias of 30.\n",
  592.          linenum);
  593.     bias = 30;
  594.       }
  595.       newpragma->Bias = bias;
  596.       bias += 6;
  597.  
  598.       newpragma->Public = public;
  599.  
  600.       AddTail((struct List *) &AmiPragmaList, (struct Node *) newpragma);
  601.  
  602.       if (*SkipBlanks(ptr+1))
  603.       { fprintf(stderr, "Line %ld, warning: Extra characters.\n", linenum);
  604.       }
  605.     }
  606.  
  607. continue_loop:
  608.   ;
  609.   }
  610.  
  611.   if (!BaseName)
  612.   { fprintf(stderr, "Error: Missing Basename.\n");
  613.   }
  614.   else
  615.   { result = TRUE;
  616.   }
  617.  
  618. exit_ScanFDFile:
  619.   fclose(fp);
  620.   return(result);
  621. }
  622.  
  623.  
  624.  
  625.  
  626.  
  627. /*
  628.     This function is similar to puts, but converts the string to lowercase.
  629.  
  630.     Inputs: Str - the string to write
  631.         Fp    - the file where to write to
  632.  
  633.     Result: TRUE, if successful, FALSE otherwise
  634. */
  635. ULONG fputslower(const STRPTR Str, FILE *Fp)
  636.  
  637. { STRPTR str = Str;
  638.  
  639.   while(*str)
  640.   { char c = tolower((int) *str);
  641.  
  642.     str++;
  643.     if (putc(c, Fp) == EOF)
  644.     { return(FALSE);
  645.     }
  646.   }
  647.   return(TRUE);
  648. }
  649.  
  650.  
  651.  
  652.  
  653.  
  654. /*
  655.     This function is similar to puts, but converts the string to uppercase.
  656.  
  657.     Inputs: Str - the string to write
  658.         Fp    - the file where to write to
  659.  
  660.     Result: TRUE, if successful, FALSE otherwise
  661. */
  662. ULONG fputsupper(const STRPTR Str, FILE *Fp)
  663.  
  664. { STRPTR str = Str;
  665.  
  666.   while(*str)
  667.   { char c = toupper((int) *str);
  668.  
  669.     str++;
  670.     if (putc(c, Fp) == EOF)
  671.     { return(FALSE);
  672.     }
  673.   }
  674.   return(TRUE);
  675. }
  676.  
  677.  
  678.  
  679.  
  680.  
  681. /*
  682.     This function writes the header of a pragma file.
  683.  
  684.     Inputs: Fp        - the file to write to.
  685.         Type    - Either "pragmas" or "lib", depending on the
  686.               typical pragma name. (Aztec uses something
  687.               like "pragmas/exec_pragmas.h" while SAS, Dice
  688.               and MAXON prefer "pragmas/exec_lib.h".)
  689.  
  690.     Result: TRUE, if successful, FALSE otherwise
  691. */
  692. ULONG WriteHeader(FILE *Fp, const STRPTR Type)
  693.  
  694. {
  695.   if (fputs("#ifndef PRAGMAS_", Fp) < 0             ||
  696.       !fputsupper(ShortBaseName, Fp)                ||
  697.       (putc('_', Fp) == EOF)                        ||
  698.       !fputsupper(Type, Fp)                         ||
  699.       fputs("_H\n#define PRAGMAS_", Fp) < 0         ||
  700.       !fputsupper(ShortBaseName, Fp)                ||
  701.       (putc('_', Fp) == EOF)                        ||
  702.       !fputsupper(Type, Fp)                         ||
  703.       fputs("_H\n\n#ifndef CLIB_", Fp) < 0          ||
  704.       !fputsupper(ShortBaseName, Fp)                ||
  705.       fputs("_PROTOS_H\n#include <clib/", Fp) < 0   ||
  706.       !fputslower(ShortBaseName, Fp)                ||
  707.       fputs("_protos.h>\n#endif\n\n", Fp) < 0)
  708.  
  709.   { return(FALSE);
  710.   }
  711.  
  712.   return(TRUE);
  713. }
  714.  
  715.  
  716.  
  717.  
  718.  
  719. /*
  720.     This function writes the footer of a pragma file.
  721.  
  722.     Inputs: Fp        - the file to write to.
  723.         Type    - Either "pragmas" or "lib", depending on the
  724.               typical pragma name. (Aztec uses something
  725.               like "pragmas/exec_pragmas.h" while SAS, Dice
  726.               and MAXON prefer "pragmas/exec_lib.h".)
  727.  
  728.     Result: TRUE, if successful, FALSE otherwise
  729. */
  730. ULONG WriteFooter(FILE *Fp, const STRPTR Type)
  731.  
  732. {
  733.   if (fputs("\n#endif\t/*  PRAGMAS_", Fp) < 0   ||
  734.       !fputsupper(ShortBaseName, Fp)            ||
  735.       (putc('_', Fp) == EOF)                    ||
  736.       !fputsupper(Type, Fp)                     ||
  737.       fputs("_H  */\n", Fp) < 0)
  738.   { return(FALSE);
  739.   }
  740.  
  741.   return(TRUE);
  742. }
  743.  
  744.  
  745.  
  746.  
  747.  
  748. /*
  749.     This function writes one pragma for Aztec-C.
  750.  
  751.     Inputs: Ap    - a pointer to the pragma which should be written.
  752.         Fp    - the file to write to
  753.  
  754.     Result: TRUE, if successful, FALSE otherwise
  755. */
  756. ULONG WriteAztecPragma(struct AmiPragma *Ap, FILE *Fp)
  757.  
  758. { int i;
  759.  
  760.   if (!Ap->Public)
  761.   { return(TRUE);
  762.   }
  763.  
  764.   if (fprintf(Fp, "#pragma amicall(%s,0x%lx,%s(",
  765.           BaseName, Ap->Bias, Ap->FuncName) < 0)
  766.   { return(FALSE);
  767.   }
  768.  
  769.   for (i = 0;  i < Ap->NumArgs;  ++i)
  770.   { if (!fputslower(RegNames[Ap->Args[i].ArgReg], Fp))
  771.     { return(FALSE);
  772.     }
  773.     if (i+1 < Ap->NumArgs  &&  putc(',', Fp) == EOF)
  774.     { return(FALSE);
  775.     }
  776.   }
  777.  
  778.   if (fputs("))\n", Fp) < 0)
  779.   { return(FALSE);
  780.   }
  781.  
  782.   return(TRUE);
  783. }
  784.  
  785.  
  786.  
  787.  
  788.  
  789. /*
  790.     This function writes one pragma for SAS-C.
  791.  
  792.     Inputs: Ap        - a pointer to the pragma which should be written.
  793.         Fp        - the file to write to
  794.         TagCall - TRUE for a tagcall pragma, FALSE for a libcall pragma
  795.  
  796.     Result: TRUE, if successful, FALSE otherwise
  797. */
  798. ULONG WriteSASPragma(struct AmiPragma *Ap, FILE *Fp, ULONG TagCall)
  799.  
  800. { int i;
  801.  
  802.   if (!Ap->Public)
  803.   { return(TRUE);
  804.   }
  805.  
  806.   if (fprintf(Fp, "#pragma %s %s %s %lx ",
  807.           TagCall ? "tagcall" : "libcall",
  808.           BaseName,
  809.           TagCall ? Ap->TagName : Ap->FuncName,
  810.           Ap->Bias) < 0)
  811.   { return(FALSE);
  812.   }
  813.  
  814.   for (i = Ap->NumArgs-1;  i >= 0;  --i)
  815.   { if ((fputc((int) HexDigits[Ap->Args[i].ArgReg], Fp) == EOF))
  816.     { return(FALSE);
  817.     }
  818.   }
  819.  
  820.   if (fprintf(Fp, "0%lc\n", HexDigits[Ap->NumArgs]) < 0)
  821.   { return(FALSE);
  822.   }
  823.  
  824.   return(TRUE);
  825. }
  826.  
  827.  
  828.  
  829.  
  830.  
  831. /*
  832.     This function creates a pragma file.
  833.  
  834.     Inputs: PragmaFile    - name of the file to be created.
  835.         PragmaExt    - TRUE, if the typical pragma filename is similar to
  836.               clib/exec_pragmas.h, FALSE for clib/exec_lib.h
  837.         SASPragmas    - TRUE for SAS-like pragmas, FALSE for Aztec
  838.         UseTags    - TRUE, if tagcall pragmas should be created.
  839.         Prototype    - TRUE, if a prototype for the library basepointer
  840.               should be created. (Dice seems to need this.)
  841.  
  842.     Result: TRUE, if successful, FALSE otherwise
  843. */
  844. ULONG CreatePragmaFile(const STRPTR PragmaFile, ULONG PragmaExt,
  845.                ULONG SASPragmas, ULONG UseTags, ULONG Prototype)
  846.  
  847. { FILE *fp;
  848.   struct AmiPragma *ap;
  849.   ULONG result = FALSE;
  850.   ULONG tagcall_seen = FALSE;
  851.  
  852.   if (!(fp = fopen((char *) PragmaFile, "w")))
  853.   { fprintf(stderr, "Error: Cannot open %s for writing.\n", PragmaFile);
  854.     return(FALSE);
  855.   }
  856.  
  857.   if (!WriteHeader(fp, (STRPTR) (PragmaExt ? "pragmas" : "lib")))
  858.   { goto exit_CreatePragmaFile;
  859.   }
  860.  
  861.   if (Prototype)
  862.   { if (fputs("#ifdef PRAGMAS_DECLARING_LIBBASE\n", fp) < 0         ||
  863.     fprintf(fp, "extern struct Library *%s;\n", BaseName) < 0   ||
  864.     fputs("#endif\n\n", fp) < 0)
  865.     { goto exit_CreatePragmaFile;
  866.     }
  867.   }
  868.  
  869.   /*
  870.       Write the pragmas.
  871.   */
  872.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  873.        ap->Node.mln_Succ;
  874.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  875.   { if ((SASPragmas  &&  !WriteSASPragma(ap, fp, FALSE))  ||
  876.     (!SASPragmas  &&  !WriteAztecPragma(ap, fp)))
  877.     { goto exit_CreatePragmaFile;
  878.     }
  879.     if (ap->TagName  &&  ap->Public)
  880.     { tagcall_seen = TRUE;
  881.     }
  882.   }
  883.   if (tagcall_seen  &&  UseTags)
  884.   { if (fputs("\n#ifdef __SASC_60\n", fp) < 0)
  885.     { goto exit_CreatePragmaFile;
  886.     }
  887.  
  888.     for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  889.      ap->Node.mln_Succ;
  890.      ap = (struct AmiPragma *) ap->Node.mln_Succ)
  891.      { if (ap->TagName  &&  !WriteSASPragma(ap, fp, TRUE))
  892.        { goto exit_CreatePragmaFile;
  893.        }
  894.      }
  895.  
  896.     if (fputs("#endif\t/*  __SASC_60  */\n", fp) < 0)
  897.     { goto exit_CreatePragmaFile;
  898.     }
  899.    }
  900.  
  901.   /*
  902.       Write the footer.
  903.   */
  904.   if (!WriteFooter(fp, (STRPTR) (PragmaExt ? "pragmas" : "lib")))
  905.   { goto exit_CreatePragmaFile;
  906.   }
  907.  
  908.   result = TRUE;
  909.  
  910. exit_CreatePragmaFile:
  911.   if (!result)
  912.   { fprintf(stderr, "Error while writing %s.\n", PragmaFile);
  913.   }
  914.   fclose(fp);
  915.   return(result);
  916. }
  917.  
  918.  
  919.  
  920.  
  921.  
  922. /*
  923.     This function creates a LVO file.
  924.  
  925.     Inputs: LVOFile - the name of the file
  926.  
  927.     Result: TRUE, if successful, FALSE otherwise
  928. */
  929. ULONG CreateLVOFile(const STRPTR LVOFile)
  930.  
  931. { FILE *fp;
  932.   struct AmiPragma *ap;
  933.   ULONG result;
  934.  
  935.   if (!(fp = fopen((char *) LVOFile, "w")))
  936.   { fprintf(stderr, "Error: Cannot open %s for writing.\n", LVOFile);
  937.     return(FALSE);
  938.   }
  939.  
  940.   if (fputs("\t\tIFND ", fp) < 0            ||
  941.       !fputsupper(ShortBaseName, fp)        ||
  942.       fputs("_LIB_I\n", fp) < 0             ||
  943.       !fputsupper(ShortBaseName, fp)        ||
  944.       fputs("_LIB_I\tSET\t1\n\n", fp) > 0)
  945.   { goto exit_CreateLVOFile;
  946.   }
  947.  
  948.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  949.        ap->Node.mln_Succ;
  950.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  951.   { if (ap->Public  &&
  952.     fprintf(fp, "\t\tXDEF\t_LVO%s\n", ap->FuncName) < 0)
  953.     { goto exit_CreateLVOFile;
  954.     }
  955.   }
  956.  
  957.   if (fputs("\n\n", fp) < 0)
  958.   { goto exit_CreateLVOFile;
  959.   }
  960.  
  961.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  962.        ap->Node.mln_Succ;
  963.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  964.   { if (ap->Public  &&
  965.     fprintf(fp, "_LVO%s\tEQU\t-%ld\n", ap->FuncName, ap->Bias) < 0)
  966.     { goto exit_CreateLVOFile;
  967.     }
  968.   }
  969.  
  970.   if (fputs("\n\t\tEND", fp) < 0)
  971.   { goto exit_CreateLVOFile;
  972.   }
  973.  
  974.   result = TRUE;
  975.  
  976. exit_CreateLVOFile:
  977.   if (!result)
  978.   { fprintf(stderr, "Error while writing %s.\n", LVOFile);
  979.   }
  980.   fclose(fp);
  981.   return(result);
  982. }
  983.  
  984.  
  985.  
  986.  
  987.  
  988. /*
  989.     This function creates an include file with the function table of
  990.     a library. (See LibHeader.c)
  991.  
  992.     Inputs: FuncTable - the name of the file to create
  993.  
  994.     Result: TRUE, if successful, FALSE otherwise
  995. */
  996. ULONG CreateFuncTable(const STRPTR FuncTable)
  997.  
  998. { FILE *fp;
  999.   struct AmiPragma *ap;
  1000.   int offset, FoundLarger;
  1001.   struct AmiPragma InternalFuncs [3];
  1002.  
  1003.   InternalFuncs[2].Bias = 18;
  1004.   InternalFuncs[2].Public = FALSE;
  1005.   InternalFuncs[2].FuncName = "_LibExpunge";
  1006.   InternalFuncs[2].TagName = NULL;
  1007.   InternalFuncs[2].NumArgs = 0;
  1008.   AddHead((struct List *) &AmiPragmaList, (struct Node *) &InternalFuncs[2]);
  1009.   InternalFuncs[1].Bias = 12;
  1010.   InternalFuncs[1].Public = FALSE;
  1011.   InternalFuncs[1].FuncName = "_LibClose";
  1012.   InternalFuncs[1].TagName = NULL;
  1013.   InternalFuncs[1].NumArgs = 0;
  1014.   AddHead((struct List *) &AmiPragmaList, (struct Node *) &InternalFuncs[1]);
  1015.   InternalFuncs[0].Bias = 6;
  1016.   InternalFuncs[0].Public = FALSE;
  1017.   InternalFuncs[0].FuncName = "_LibOpen";
  1018.   InternalFuncs[0].TagName = NULL;
  1019.   InternalFuncs[0].NumArgs = 0;
  1020.   AddHead((struct List *) &AmiPragmaList, (struct Node *) &InternalFuncs[0]);
  1021.  
  1022.   if (!(fp = fopen((char *) FuncTable, "w")))
  1023.     { 
  1024.       fprintf(stderr, "Error: Cannot open %s for writing.\n", FuncTable);
  1025.       return(FALSE);
  1026.     }
  1027.  
  1028.   if (fprintf(fp, "\n/*\n    MACHINE GENERATED (Do not edit)\n*/\n\n") < 0)
  1029.     { return(FALSE);
  1030.     }
  1031.  
  1032.   offset = 24;
  1033.   do
  1034.     {
  1035.       offset += 6;
  1036.       FoundLarger = FALSE;
  1037.       for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1038.        ap->Node.mln_Succ;
  1039.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1040.     {
  1041.       if (ap->Bias >= offset)
  1042.         {
  1043.           FoundLarger = TRUE;
  1044.           if (ap->Bias == offset  &&
  1045.           fprintf(fp, "extern REGARGS VOID %s(struct Library *);\n",
  1046.               ap->FuncName) < 0)
  1047.         {
  1048.           return(FALSE);
  1049.         }
  1050.           break;
  1051.         }
  1052.     }
  1053.     }
  1054.   while (FoundLarger);
  1055.  
  1056.   if (fprintf(fp, "\nconst STATIC APTR LibFuncTable[] =\n  {\n") < 0)
  1057.     { return(FALSE);
  1058.     }
  1059.  
  1060.   offset = 0;
  1061.   do
  1062.     {
  1063.       offset += 6;
  1064.       FoundLarger = FALSE;
  1065.       for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1066.        ap->Node.mln_Succ;
  1067.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1068.     {
  1069.       if (ap->Bias >= offset)
  1070.         {
  1071.           FoundLarger = TRUE;
  1072.           if (fprintf(fp, "    %s,\n",
  1073.               ap->Bias == offset ? ap->FuncName : 
  1074.                                    (STRPTR) "_LibNull") < 0)
  1075.         { return(FALSE);
  1076.         }
  1077.           break;
  1078.         }
  1079.     }
  1080.     }
  1081.   while (FoundLarger);
  1082.  
  1083.   if (fprintf(fp, "    (APTR)-1\n  };\n") < 0)
  1084.     { return(FALSE);
  1085.     }
  1086.  
  1087.   fclose(fp);
  1088.   return(TRUE);
  1089. }
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096. /*
  1097.     This function creates stub routines for the tag functions.
  1098.  
  1099.     Inputs: TagDir  - a pointer to the directory, where to store the created
  1100.               sources.
  1101.  
  1102.     Result: TRUE, if successful, FALSE otherwise
  1103. */
  1104. ULONG CreateTagFuncs(const STRPTR TagDir)
  1105.  
  1106. { FILE *fp;
  1107.   struct AmiPragma *ap;
  1108.  
  1109.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1110.        ap->Node.mln_Succ;
  1111.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1112.   { if (ap->TagName  &&  ap->Public)
  1113.     { STRPTR sourcename;
  1114.       ULONG size = strlen((char *) TagDir) +
  1115.            strlen((char *) ap->TagName) + 128;
  1116.       ULONG i;
  1117.       ULONG result = FALSE;
  1118.  
  1119.       /*
  1120.       Get name of sourcefile to create.
  1121.       */
  1122.       if (!(sourcename = strndup(TagDir, size)))
  1123.       { MemError();
  1124.     return(FALSE);
  1125.       }
  1126.       AddPart(sourcename, ap->TagName, size);
  1127.       strcat((char *) sourcename, ".c");
  1128.  
  1129.       /*
  1130.       Open sourcefile.
  1131.       */
  1132.       if (!(fp = fopen((char *) sourcename, "w")))
  1133.       { fprintf(stderr, "Error: Cannot open %s for writing.\n", sourcename);
  1134.     return(FALSE);
  1135.       }
  1136.  
  1137.       if (fputs("typedef unsigned long ULONG;\n", fp) < 0               ||
  1138.       fprintf(fp, "extern struct Library *%s;\n", BaseName) < 0     ||
  1139.       fprintf(fp, "extern ULONG %s(", ap->FuncName) < 0)
  1140.       { goto exit_CreateTagFuncs;
  1141.       }
  1142.       for(i = 0;  i < ap->NumArgs;  i++)
  1143.       { if (fputs("ULONG", fp) < 0)
  1144.     { goto exit_CreateTagFuncs;
  1145.     }
  1146.     if (i+1 < ap->NumArgs  &&  fputs(", ", fp) < 0)
  1147.     { goto exit_CreateTagFuncs;
  1148.     }
  1149.       }
  1150.       if (fputs(");\n\n", fp) < 0                                           ||
  1151.       fputs("#if defined(AZTEC_C)  ||  defined(__MAXON__)\n", fp) < 0   ||
  1152.       !WriteAztecPragma(ap, fp)                                         ||
  1153.       fputs("#endif\n\n", fp) < 0                                       ||
  1154.       fputs("#if defined(_DCC)  ||  defined(__SASC)\n", fp) < 0         ||
  1155.       !WriteSASPragma(ap, fp, FALSE)                                    ||
  1156.       fputs("#endif\n\n\n", fp) < 0                                     ||
  1157.       fprintf(fp, "ULONG %s(", ap->TagName) < 0)
  1158.       { goto exit_CreateTagFuncs;
  1159.       }
  1160.       for (i = 0;  i < ap->NumArgs;  i++)
  1161.       { if (fprintf(fp, "ULONG %s, ", ap->Args[i].ArgName) < 0)
  1162.     { goto exit_CreateTagFuncs;
  1163.     }
  1164.       }
  1165.       if (fputs("...)\n\n", fp) < 0                         ||
  1166.       fprintf(fp, "{ return(%s(", ap->FuncName) < 0)
  1167.       { goto exit_CreateTagFuncs;
  1168.       }
  1169.       for (i = 0;  i < ap->NumArgs-1;  i++)
  1170.       { if (fprintf(fp, "%s, ", ap->Args[i].ArgName) < 0)
  1171.     { goto exit_CreateTagFuncs;
  1172.     }
  1173.       }
  1174.       if (fprintf(fp, "(ULONG) &%s));\n}\n", ap->Args[ap->NumArgs-1].ArgName) < 0)
  1175.       { goto exit_CreateTagFuncs;
  1176.       }
  1177.  
  1178.       result = TRUE;
  1179.  
  1180. exit_CreateTagFuncs:
  1181.       if (!result)
  1182.       { fprintf(stderr, "Error while writing %s.\n", sourcename);
  1183.       }
  1184.       fclose(fp);
  1185.       free(sourcename);
  1186.       if (!result)
  1187.       { return(FALSE);
  1188.       }
  1189.     }
  1190.   }
  1191.  
  1192.   return(TRUE);
  1193. }
  1194.  
  1195.  
  1196.  
  1197.  
  1198.  
  1199. /*
  1200.     This is main().
  1201. */
  1202. void main (int argc, char *argv[])
  1203.  
  1204. { struct RDArgs *rdargs;
  1205.   struct
  1206.   { STRPTR FDFILE;
  1207.     STRPTR AZTEC;
  1208.     STRPTR AS;
  1209.     STRPTR SAS;
  1210.     STRPTR DICE;
  1211.     STRPTR MAXON;
  1212.     STRPTR TAGDIR;
  1213.     STRPTR FUNCTABLE;
  1214.     ULONG HELP;
  1215.   } args = {NULL, NULL, NULL, NULL, NULL, NULL, FALSE};
  1216.   extern struct Library *SysBase;
  1217.  
  1218.   if (!argc)        /*  Prevent calling from Workbench.     */
  1219.   { exit(-1);
  1220.   }
  1221.  
  1222.   if (SysBase->lib_Version < 36)
  1223.   { fprintf(stderr, "Need at least Kickstart 2.0.\n");
  1224.     exit(20);
  1225.   }
  1226.  
  1227.   if (!(rdargs = ReadArgs((STRPTR) TEMPLATE, (LONG *) &args, NULL)))
  1228.   { Usage();
  1229.   }
  1230.  
  1231.   if(args.HELP)
  1232.   { Usage();
  1233.   }
  1234.  
  1235.   if (ScanFDFile(args.FDFILE))
  1236.   { if ((args.AZTEC  &&
  1237.      !CreatePragmaFile(args.AZTEC, FALSE, FALSE, FALSE, TRUE))          ||
  1238.     (args.AS  &&
  1239.      !CreateLVOFile(args.AS))                                           ||
  1240.     (args.SAS  &&
  1241.      !CreatePragmaFile(args.SAS, TRUE, TRUE, TRUE, TRUE))               ||
  1242.     (args.MAXON  &&
  1243.      !CreatePragmaFile(args.MAXON, TRUE, FALSE, FALSE, TRUE))           ||
  1244.     (args.DICE  &&
  1245.      !CreatePragmaFile(args.DICE, TRUE, TRUE, TRUE, TRUE))              ||
  1246.     (args.TAGDIR  &&
  1247.      !CreateTagFuncs(args.TAGDIR))                                      ||
  1248.     (args.FUNCTABLE  &&
  1249.      !CreateFuncTable(args.FUNCTABLE)))
  1250.     { exit(5);
  1251.     }
  1252.   }
  1253.   exit(0);
  1254. }
  1255.